1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.google.common.io;
18
19 import static com.google.common.base.Preconditions.checkArgument;
20 import static com.google.common.base.Preconditions.checkNotNull;
21 import static com.google.common.base.Preconditions.checkPositionIndex;
22
23 import com.google.common.annotations.Beta;
24
25 import java.io.ByteArrayInputStream;
26 import java.io.ByteArrayOutputStream;
27 import java.io.DataInput;
28 import java.io.DataInputStream;
29 import java.io.DataOutput;
30 import java.io.DataOutputStream;
31 import java.io.EOFException;
32 import java.io.FilterInputStream;
33 import java.io.IOException;
34 import java.io.InputStream;
35 import java.io.OutputStream;
36 import java.nio.ByteBuffer;
37 import java.nio.channels.ReadableByteChannel;
38 import java.nio.channels.WritableByteChannel;
39 import java.util.Arrays;
40
41
42
43
44
45
46
47
48 @Beta
49 public final class ByteStreams {
50 private static final int BUF_SIZE = 0x1000;
51
52 private ByteStreams() {}
53
54
55
56
57
58
59
60
61
62
63 public static long copy(InputStream from, OutputStream to)
64 throws IOException {
65 checkNotNull(from);
66 checkNotNull(to);
67 byte[] buf = new byte[BUF_SIZE];
68 long total = 0;
69 while (true) {
70 int r = from.read(buf);
71 if (r == -1) {
72 break;
73 }
74 to.write(buf, 0, r);
75 total += r;
76 }
77 return total;
78 }
79
80
81
82
83
84
85
86
87
88
89 public static long copy(ReadableByteChannel from,
90 WritableByteChannel to) throws IOException {
91 checkNotNull(from);
92 checkNotNull(to);
93 ByteBuffer buf = ByteBuffer.allocate(BUF_SIZE);
94 long total = 0;
95 while (from.read(buf) != -1) {
96 buf.flip();
97 while (buf.hasRemaining()) {
98 total += to.write(buf);
99 }
100 buf.clear();
101 }
102 return total;
103 }
104
105
106
107
108
109
110
111
112
113 public static byte[] toByteArray(InputStream in) throws IOException {
114 ByteArrayOutputStream out = new ByteArrayOutputStream();
115 copy(in, out);
116 return out.toByteArray();
117 }
118
119
120
121
122
123
124
125 static byte[] toByteArray(
126 InputStream in, int expectedSize) throws IOException {
127 byte[] bytes = new byte[expectedSize];
128 int remaining = expectedSize;
129
130 while (remaining > 0) {
131 int off = expectedSize - remaining;
132 int read = in.read(bytes, off, remaining);
133 if (read == -1) {
134
135
136 return Arrays.copyOf(bytes, off);
137 }
138 remaining -= read;
139 }
140
141
142 int b = in.read();
143 if (b == -1) {
144 return bytes;
145 }
146
147
148 FastByteArrayOutputStream out = new FastByteArrayOutputStream();
149 out.write(b);
150 copy(in, out);
151
152 byte[] result = new byte[bytes.length + out.size()];
153 System.arraycopy(bytes, 0, result, 0, bytes.length);
154 out.writeTo(result, bytes.length);
155 return result;
156 }
157
158
159
160
161 private static final class FastByteArrayOutputStream
162 extends ByteArrayOutputStream {
163
164
165
166
167 void writeTo(byte[] b, int off) {
168 System.arraycopy(buf, 0, b, off, count);
169 }
170 }
171
172
173
174
175
176 public static ByteArrayDataInput newDataInput(byte[] bytes) {
177 return newDataInput(new ByteArrayInputStream(bytes));
178 }
179
180
181
182
183
184
185
186
187 public static ByteArrayDataInput newDataInput(byte[] bytes, int start) {
188 checkPositionIndex(start, bytes.length);
189 return newDataInput(
190 new ByteArrayInputStream(bytes, start, bytes.length - start));
191 }
192
193
194
195
196
197
198
199
200 public static ByteArrayDataInput newDataInput(
201 ByteArrayInputStream byteArrayInputStream) {
202 return new ByteArrayDataInputStream(checkNotNull(byteArrayInputStream));
203 }
204
205 private static class ByteArrayDataInputStream implements ByteArrayDataInput {
206 final DataInput input;
207
208 ByteArrayDataInputStream(ByteArrayInputStream byteArrayInputStream) {
209 this.input = new DataInputStream(byteArrayInputStream);
210 }
211
212 @Override public void readFully(byte b[]) {
213 try {
214 input.readFully(b);
215 } catch (IOException e) {
216 throw new IllegalStateException(e);
217 }
218 }
219
220 @Override public void readFully(byte b[], int off, int len) {
221 try {
222 input.readFully(b, off, len);
223 } catch (IOException e) {
224 throw new IllegalStateException(e);
225 }
226 }
227
228 @Override public int skipBytes(int n) {
229 try {
230 return input.skipBytes(n);
231 } catch (IOException e) {
232 throw new IllegalStateException(e);
233 }
234 }
235
236 @Override public boolean readBoolean() {
237 try {
238 return input.readBoolean();
239 } catch (IOException e) {
240 throw new IllegalStateException(e);
241 }
242 }
243
244 @Override public byte readByte() {
245 try {
246 return input.readByte();
247 } catch (EOFException e) {
248 throw new IllegalStateException(e);
249 } catch (IOException impossible) {
250 throw new AssertionError(impossible);
251 }
252 }
253
254 @Override public int readUnsignedByte() {
255 try {
256 return input.readUnsignedByte();
257 } catch (IOException e) {
258 throw new IllegalStateException(e);
259 }
260 }
261
262 @Override public short readShort() {
263 try {
264 return input.readShort();
265 } catch (IOException e) {
266 throw new IllegalStateException(e);
267 }
268 }
269
270 @Override public int readUnsignedShort() {
271 try {
272 return input.readUnsignedShort();
273 } catch (IOException e) {
274 throw new IllegalStateException(e);
275 }
276 }
277
278 @Override public char readChar() {
279 try {
280 return input.readChar();
281 } catch (IOException e) {
282 throw new IllegalStateException(e);
283 }
284 }
285
286 @Override public int readInt() {
287 try {
288 return input.readInt();
289 } catch (IOException e) {
290 throw new IllegalStateException(e);
291 }
292 }
293
294 @Override public long readLong() {
295 try {
296 return input.readLong();
297 } catch (IOException e) {
298 throw new IllegalStateException(e);
299 }
300 }
301
302 @Override public float readFloat() {
303 try {
304 return input.readFloat();
305 } catch (IOException e) {
306 throw new IllegalStateException(e);
307 }
308 }
309
310 @Override public double readDouble() {
311 try {
312 return input.readDouble();
313 } catch (IOException e) {
314 throw new IllegalStateException(e);
315 }
316 }
317
318 @Override public String readLine() {
319 try {
320 return input.readLine();
321 } catch (IOException e) {
322 throw new IllegalStateException(e);
323 }
324 }
325
326 @Override public String readUTF() {
327 try {
328 return input.readUTF();
329 } catch (IOException e) {
330 throw new IllegalStateException(e);
331 }
332 }
333 }
334
335
336
337
338 public static ByteArrayDataOutput newDataOutput() {
339 return newDataOutput(new ByteArrayOutputStream());
340 }
341
342
343
344
345
346
347
348 public static ByteArrayDataOutput newDataOutput(int size) {
349 checkArgument(size >= 0, "Invalid size: %s", size);
350 return newDataOutput(new ByteArrayOutputStream(size));
351 }
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367 public static ByteArrayDataOutput newDataOutput(
368 ByteArrayOutputStream byteArrayOutputSteam) {
369 return new ByteArrayDataOutputStream(checkNotNull(byteArrayOutputSteam));
370 }
371
372 @SuppressWarnings("deprecation")
373 private static class ByteArrayDataOutputStream
374 implements ByteArrayDataOutput {
375
376 final DataOutput output;
377 final ByteArrayOutputStream byteArrayOutputSteam;
378
379 ByteArrayDataOutputStream(ByteArrayOutputStream byteArrayOutputSteam) {
380 this.byteArrayOutputSteam = byteArrayOutputSteam;
381 output = new DataOutputStream(byteArrayOutputSteam);
382 }
383
384 @Override public void write(int b) {
385 try {
386 output.write(b);
387 } catch (IOException impossible) {
388 throw new AssertionError(impossible);
389 }
390 }
391
392 @Override public void write(byte[] b) {
393 try {
394 output.write(b);
395 } catch (IOException impossible) {
396 throw new AssertionError(impossible);
397 }
398 }
399
400 @Override public void write(byte[] b, int off, int len) {
401 try {
402 output.write(b, off, len);
403 } catch (IOException impossible) {
404 throw new AssertionError(impossible);
405 }
406 }
407
408 @Override public void writeBoolean(boolean v) {
409 try {
410 output.writeBoolean(v);
411 } catch (IOException impossible) {
412 throw new AssertionError(impossible);
413 }
414 }
415
416 @Override public void writeByte(int v) {
417 try {
418 output.writeByte(v);
419 } catch (IOException impossible) {
420 throw new AssertionError(impossible);
421 }
422 }
423
424 @Override public void writeBytes(String s) {
425 try {
426 output.writeBytes(s);
427 } catch (IOException impossible) {
428 throw new AssertionError(impossible);
429 }
430 }
431
432 @Override public void writeChar(int v) {
433 try {
434 output.writeChar(v);
435 } catch (IOException impossible) {
436 throw new AssertionError(impossible);
437 }
438 }
439
440 @Override public void writeChars(String s) {
441 try {
442 output.writeChars(s);
443 } catch (IOException impossible) {
444 throw new AssertionError(impossible);
445 }
446 }
447
448 @Override public void writeDouble(double v) {
449 try {
450 output.writeDouble(v);
451 } catch (IOException impossible) {
452 throw new AssertionError(impossible);
453 }
454 }
455
456 @Override public void writeFloat(float v) {
457 try {
458 output.writeFloat(v);
459 } catch (IOException impossible) {
460 throw new AssertionError(impossible);
461 }
462 }
463
464 @Override public void writeInt(int v) {
465 try {
466 output.writeInt(v);
467 } catch (IOException impossible) {
468 throw new AssertionError(impossible);
469 }
470 }
471
472 @Override public void writeLong(long v) {
473 try {
474 output.writeLong(v);
475 } catch (IOException impossible) {
476 throw new AssertionError(impossible);
477 }
478 }
479
480 @Override public void writeShort(int v) {
481 try {
482 output.writeShort(v);
483 } catch (IOException impossible) {
484 throw new AssertionError(impossible);
485 }
486 }
487
488 @Override public void writeUTF(String s) {
489 try {
490 output.writeUTF(s);
491 } catch (IOException impossible) {
492 throw new AssertionError(impossible);
493 }
494 }
495
496 @Override public byte[] toByteArray() {
497 return byteArrayOutputSteam.toByteArray();
498 }
499 }
500
501 private static final OutputStream NULL_OUTPUT_STREAM =
502 new OutputStream() {
503
504 @Override public void write(int b) {
505 }
506
507 @Override public void write(byte[] b) {
508 checkNotNull(b);
509 }
510
511 @Override public void write(byte[] b, int off, int len) {
512 checkNotNull(b);
513 }
514
515 @Override
516 public String toString() {
517 return "ByteStreams.nullOutputStream()";
518 }
519 };
520
521
522
523
524
525
526 public static OutputStream nullOutputStream() {
527 return NULL_OUTPUT_STREAM;
528 }
529
530
531
532
533
534
535
536
537
538
539 public static InputStream limit(InputStream in, long limit) {
540 return new LimitedInputStream(in, limit);
541 }
542
543 private static final class LimitedInputStream extends FilterInputStream {
544
545 private long left;
546 private long mark = -1;
547
548 LimitedInputStream(InputStream in, long limit) {
549 super(in);
550 checkNotNull(in);
551 checkArgument(limit >= 0, "limit must be non-negative");
552 left = limit;
553 }
554
555 @Override public int available() throws IOException {
556 return (int) Math.min(in.available(), left);
557 }
558
559
560 @Override public synchronized void mark(int readLimit) {
561 in.mark(readLimit);
562 mark = left;
563 }
564
565 @Override public int read() throws IOException {
566 if (left == 0) {
567 return -1;
568 }
569
570 int result = in.read();
571 if (result != -1) {
572 --left;
573 }
574 return result;
575 }
576
577 @Override public int read(byte[] b, int off, int len) throws IOException {
578 if (left == 0) {
579 return -1;
580 }
581
582 len = (int) Math.min(len, left);
583 int result = in.read(b, off, len);
584 if (result != -1) {
585 left -= result;
586 }
587 return result;
588 }
589
590 @Override public synchronized void reset() throws IOException {
591 if (!in.markSupported()) {
592 throw new IOException("Mark not supported");
593 }
594 if (mark == -1) {
595 throw new IOException("Mark not set");
596 }
597
598 in.reset();
599 left = mark;
600 }
601
602 @Override public long skip(long n) throws IOException {
603 n = Math.min(n, left);
604 long skipped = in.skip(n);
605 left -= skipped;
606 return skipped;
607 }
608 }
609
610
611
612
613
614
615
616
617
618
619
620
621 public static void readFully(InputStream in, byte[] b) throws IOException {
622 readFully(in, b, 0, b.length);
623 }
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639 public static void readFully(
640 InputStream in, byte[] b, int off, int len) throws IOException {
641 int read = read(in, b, off, len);
642 if (read != len) {
643 throw new EOFException("reached end of stream after reading "
644 + read + " bytes; " + len + " bytes expected");
645 }
646 }
647
648
649
650
651
652
653
654
655
656
657
658
659
660 public static void skipFully(InputStream in, long n) throws IOException {
661 long toSkip = n;
662 while (n > 0) {
663 long amt = in.skip(n);
664 if (amt == 0) {
665
666 if (in.read() == -1) {
667 long skipped = toSkip - n;
668 throw new EOFException("reached end of stream after skipping "
669 + skipped + " bytes; " + toSkip + " bytes expected");
670 }
671 n--;
672 } else {
673 n -= amt;
674 }
675 }
676 }
677
678
679
680
681
682
683
684
685
686
687 public static <T> T readBytes(
688 InputStream input, ByteProcessor<T> processor) throws IOException {
689 checkNotNull(input);
690 checkNotNull(processor);
691
692 byte[] buf = new byte[BUF_SIZE];
693 int read;
694 do {
695 read = input.read(buf);
696 } while (read != -1 && processor.processBytes(buf, 0, read));
697 return processor.getResult();
698 }
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724 public static int read(InputStream in, byte[] b, int off, int len)
725 throws IOException {
726 checkNotNull(in);
727 checkNotNull(b);
728 if (len < 0) {
729 throw new IndexOutOfBoundsException("len is negative");
730 }
731 int total = 0;
732 while (total < len) {
733 int result = in.read(b, off + total, len - total);
734 if (result == -1) {
735 break;
736 }
737 total += result;
738 }
739 return total;
740 }
741 }